/**
 * 麦克风SDK音频处理模块
 * 负责音频数据处理、分析和回放
 */

import eventEmitter, { EventTypes } from './events.js';
import { debugLog, clamp } from './utils.js';

// 音频上下文和处理节点
let audioContext = null;
let analyser = null;
let gainNode = null;
let mediaStreamSource = null;
let audioProcessor = null;

// 音频数据
let audioBuffer = [];
let isRecording = false;
let audioLevel = 0;
let gainValue = 1.0;

// 回放相关
let isPlayingBack = false;
let playbackSource = null;

// 原始麦克风流
let microphoneStream = null;

// 音频处理节点
let scriptProcessor = null;

// 音频数据回调函数列表
const audioDataCallbacks = new Set();

// 音频处理配置
const processingConfig = {
  // 是否启用音频处理
  enabled: true,
  // 采样率
  sampleRate: 44100,
  // 缓冲区大小
  bufferSize: 4096,
  // 输入通道数
  inputChannels: 1,
  // 输出通道数
  outputChannels: 1
};

/**
 * 初始化音频处理器
 * @returns {Promise<boolean>} 初始化是否成功
 */
export async function initAudioProcessor() {
  try {
    // 如果已经初始化，则返回
    if (audioContext) {
      return true;
    }
    
    // 创建音频上下文
    const AudioContext = window.AudioContext || window.webkitAudioContext;
    if (!AudioContext) {
      throw new Error('浏览器不支持AudioContext');
    }
    
    audioContext = new AudioContext();
    
    // 创建分析器节点
    analyser = audioContext.createAnalyser();
    analyser.fftSize = 2048;
    analyser.smoothingTimeConstant = 0.8;
    
    // 创建增益节点
    gainNode = audioContext.createGain();
    gainNode.gain.value = gainValue;
    
    // 连接节点
    gainNode.connect(analyser);
    analyser.connect(audioContext.destination);
    
    // 启动音频电平分析
    startLevelAnalysis();
    
    debugLog('音频处理器初始化成功');
    return true;
  } catch (error) {
    debugLog('音频处理器初始化失败:', error);
    eventEmitter.emit(EventTypes.ERROR, {
      type: 'audio_processor_init',
      message: '音频处理器初始化失败',
      error
    });
    return false;
  }
}

/**
 * 解锁音频上下文（在移动设备上需要用户交互才能启动音频上下文）
 * @returns {Promise<boolean>} 解锁是否成功
 */
export async function unlockAudioContext() {
  if (!audioContext) {
    await initAudioProcessor();
  }
  
  // 如果音频上下文已经运行，则不需要解锁
  if (audioContext.state === 'running') {
    return true;
  }
  
  try {
    // 创建一个空的缓冲区并播放，以解锁音频上下文
    const buffer = audioContext.createBuffer(1, 1, 22050);
    const source = audioContext.createBufferSource();
    source.buffer = buffer;
    source.connect(audioContext.destination);
    source.start(0);
    
    // 恢复音频上下文
    await audioContext.resume();
    
    debugLog('音频上下文已解锁');
    return true;
  } catch (error) {
    debugLog('解锁音频上下文失败:', error);
    eventEmitter.emit(EventTypes.ERROR, {
      type: 'audio_context_unlock',
      message: '解锁音频上下文失败',
      error
    });
    return false;
  }
}

/**
 * 连接麦克风流到音频处理器
 * @param {MediaStream} stream - 麦克风媒体流
 */
export function connectMicrophoneStream(stream) {
  if (!audioContext) {
    throw new Error('音频处理器未初始化');
  }
  
  // 如果流为null，则返回false
  if (!stream) {
    debugLog('传入的麦克风流为null');
    return false;
  }
  
  try {
    // 断开之前的连接
    disconnectMicrophoneStream();
    
    // 保存原始麦克风流，以便外部系统可以访问
    microphoneStream = stream;
    
    // 创建媒体流源节点
    mediaStreamSource = audioContext.createMediaStreamSource(stream);
    
    // 创建脚本处理节点，用于处理音频数据
    scriptProcessor = audioContext.createScriptProcessor(
      processingConfig.bufferSize,
      processingConfig.inputChannels,
      processingConfig.outputChannels
    );
    
    // 设置音频处理回调
    scriptProcessor.onaudioprocess = handleAudioProcess;
    
    // 连接节点
    mediaStreamSource.connect(gainNode);
    
    // 如果启用了音频处理，则连接脚本处理节点
    if (processingConfig.enabled) {
      gainNode.connect(scriptProcessor);
      scriptProcessor.connect(audioContext.destination);
    }
    
    // 开始录制
    isRecording = true;
    audioBuffer = [];
    
    // 发送流已连接事件
    eventEmitter.emit(EventTypes.MICROPHONE_CONNECTED, { stream });
    
    debugLog('麦克风流已连接到音频处理器');
    
    // 返回成功
    return true;
  } catch (error) {
    debugLog('连接麦克风流失败:', error);
    eventEmitter.emit(EventTypes.ERROR, {
      type: 'microphone_connect',
      message: '连接麦克风流失败',
      error
    });
    throw error;
  }
}

/**
 * 处理音频数据
 * @param {AudioProcessingEvent} event - 音频处理事件
 */
function handleAudioProcess(event) {
  // 获取输入数据
  const inputBuffer = event.inputBuffer;
  const inputData = inputBuffer.getChannelData(0);
  
  // 如果有注册的回调函数，则调用它们
  if (audioDataCallbacks.size > 0) {
    // 创建一个副本，以避免修改原始数据
    const audioData = new Float32Array(inputData);
    
    // 调用所有回调函数
    audioDataCallbacks.forEach(callback => {
      try {
        callback({
          audioData,
          sampleRate: inputBuffer.sampleRate,
          timestamp: performance.now()
        });
      } catch (error) {
        debugLog('音频数据回调执行失败:', error);
        // 通知用户
        eventEmitter.emit(EventTypes.ERROR, {
          type: 'audio_data_callback',
          message: '音频数据回调执行失败',
          error
        });
      }
    });
  }
}

/**
 * 断开麦克风流
 */
export function disconnectMicrophoneStream() {
  if (mediaStreamSource) {
    try {
      mediaStreamSource.disconnect();
      mediaStreamSource = null;
      
      if (scriptProcessor) {
        scriptProcessor.disconnect();
        scriptProcessor.onaudioprocess = null;
        scriptProcessor = null;
      }
      
      // 停止所有轨道
      if (microphoneStream) {
        microphoneStream.getTracks().forEach(track => track.stop());
        microphoneStream = null;
      }
      
      isRecording = false;
      
      // 发送流已断开事件
      eventEmitter.emit(EventTypes.MICROPHONE_DISCONNECTED);
      
      debugLog('麦克风流已断开');
    } catch (error) {
      debugLog('断开麦克风流失败:', error);
    }
  }
}

/**
 * 开始音频电平分析
 */
function startLevelAnalysis() {
  if (!analyser) {
    return;
  }
  
  const dataArray = new Uint8Array(analyser.frequencyBinCount);
  
  const updateLevel = () => {
    if (!analyser) {
      return;
    }
    
    // 获取音频数据
    analyser.getByteFrequencyData(dataArray);
    
    // 计算平均音量
    let sum = 0;
    for (let i = 0; i < dataArray.length; i++) {
      sum += dataArray[i];
    }
    
    // 计算音频电平（0-1范围）
    const newLevel = sum / (dataArray.length * 255);
    
    // 如果电平变化超过阈值，则发送事件
    if (Math.abs(newLevel - audioLevel) > 0.01) {
      audioLevel = newLevel;
      eventEmitter.emit(EventTypes.AUDIO_LEVEL, audioLevel);
    }
    
    // 如果正在录制，则保存音频数据
    if (isRecording && audioContext) {
      // 这里可以添加录制逻辑，例如使用MediaRecorder API
    }
    
    // 继续分析
    requestAnimationFrame(updateLevel);
  };
  
  // 开始分析
  updateLevel();
}

/**
 * 停止音频电平分析
 */
function stopLevelAnalysis() {
  // 由于音频电平分析是通过requestAnimationFrame实现的
  // 我们不需要显式地停止它，因为如果analyser被设置为null
  // 或者在下一次调用updateLevel函数时会自动停止
  
  // 这里可以添加一些清理逻辑，如果需要的话
  debugLog('音频电平分析已停止');
}

/**
 * 设置增益值
 * @param {number} value - 增益值（0-1范围）
 */
export function setGain(value) {
  gainValue = clamp(value, 0, 1);
  
  if (gainNode) {
    gainNode.gain.value = gainValue;
    debugLog('增益值已设置为:', gainValue);
  }
}

/**
 * 获取当前增益值
 * @returns {number} 当前增益值
 */
export function getGain() {
  return gainValue;
}

/**
 * 获取当前音频电平
 * @returns {number} 当前音频电平（0-1范围）
 */
export function getAudioLevel() {
  return audioLevel;
}

/**
 * 播放音频
 * @param {ArrayBuffer} buffer - 音频数据
 * @returns {Promise<void>}
 */
export async function playAudio(buffer) {
  if (!audioContext) {
    await initAudioProcessor();
  }
  
  // 如果正在播放，则停止
  if (isPlayingBack) {
    stopPlayback();
  }
  
  try {
    // 解码音频数据
    const audioBuffer = await audioContext.decodeAudioData(buffer);
    
    // 创建音频源
    playbackSource = audioContext.createBufferSource();
    playbackSource.buffer = audioBuffer;
    
    // 连接到增益节点
    playbackSource.connect(gainNode);
    
    // 设置播放结束回调
    playbackSource.onended = () => {
      isPlayingBack = false;
      eventEmitter.emit(EventTypes.PLAYBACK_STATUS, { isPlaying: false });
      debugLog('音频播放结束');
    };
    
    // 开始播放
    playbackSource.start(0);
    isPlayingBack = true;
    
    // 发送播放状态事件
    eventEmitter.emit(EventTypes.PLAYBACK_STATUS, { isPlaying: true });
    
    debugLog('开始播放音频');
  } catch (error) {
    debugLog('播放音频失败:', error);
    eventEmitter.emit(EventTypes.ERROR, {
      type: 'audio_playback',
      message: '播放音频失败',
      error
    });
    throw error;
  }
}

/**
 * 停止音频播放
 */
export function stopPlayback() {
  if (playbackSource && isPlayingBack) {
    try {
      playbackSource.stop();
      playbackSource.disconnect();
      playbackSource = null;
      isPlayingBack = false;
      
      // 发送播放状态事件
      eventEmitter.emit(EventTypes.PLAYBACK_STATUS, { isPlaying: false });
      
      debugLog('音频播放已停止');
    } catch (error) {
      debugLog('停止音频播放失败:', error);
    }
  }
}

/**
 * 获取播放状态
 * @returns {boolean} 是否正在播放
 */
export function isPlaying() {
  return isPlayingBack;
}

/**
 * 获取原始麦克风媒体流
 * @returns {MediaStream|null} 麦克风媒体流
 */
export function getMicrophoneStream() {
  return microphoneStream;
}

/**
 * 注册音频数据回调函数
 * @param {Function} callback - 回调函数，接收音频数据对象 {audioData, sampleRate, timestamp}
 * @returns {Function} 取消注册的函数
 */
export function registerAudioDataCallback(callback) {
  // 如果没有提供回调或回调不是函数，则直接返回一个空函数
  if (!callback || typeof callback !== 'function') {
    debugLog('注册音频数据回调失败：回调必须是一个函数');
    return () => {}; // 返回一个空函数作为取消注册的函数
  }
  
  audioDataCallbacks.add(callback);
  debugLog('已注册音频数据回调函数，当前回调数量:', audioDataCallbacks.size);
  
  // 返回取消注册的函数
  return () => {
    audioDataCallbacks.delete(callback);
    debugLog('已取消注册音频数据回调函数，当前回调数量:', audioDataCallbacks.size);
  };
}

/**
 * 设置音频处理配置
 * @param {Object} config - 配置对象
 * @param {boolean} [config.enabled] - 是否启用音频处理
 * @param {number} [config.sampleRate] - 采样率
 * @param {number} [config.bufferSize] - 缓冲区大小
 * @param {number} [config.inputChannels] - 输入通道数
 * @param {number} [config.outputChannels] - 输出通道数
 */
export function setProcessingConfig(config) {
  // 保存旧配置
  const oldConfig = { ...processingConfig };
  
  // 更新配置
  Object.assign(processingConfig, config);
  
  debugLog('音频处理配置已更新:', processingConfig);
  
  // 检查关键配置是否改变
  const needReconnect = 
    oldConfig.enabled !== processingConfig.enabled ||
    oldConfig.bufferSize !== processingConfig.bufferSize ||
    oldConfig.inputChannels !== processingConfig.inputChannels ||
    oldConfig.outputChannels !== processingConfig.outputChannels;
  
  // 如果关键配置改变且已连接麦克风流，则重新连接
  if (needReconnect && microphoneStream) {
    debugLog('关键音频配置已改变，重新连接麦克风流');
    connectMicrophoneStream(microphoneStream);
  }
}

/**
 * 获取当前音频处理配置
 * @returns {Object} 当前配置
 */
export function getProcessingConfig() {
  return { ...processingConfig };
}

/**
 * 释放音频处理器资源
 */
export function dispose() {
  // 停止播放
  stopPlayback();
  
  // 断开麦克风流
  disconnectMicrophoneStream();
  
  // 清空回调函数
  audioDataCallbacks.clear();
  
  // 关闭音频上下文
  if (audioContext) {
    audioContext.close().catch(error => {
      debugLog('关闭音频上下文失败:', error);
    });
    
    audioContext = null;
    analyser = null;
    gainNode = null;
    scriptProcessor = null;
  }
  
  debugLog('音频处理器资源已释放');
}

// 导出音频处理器
export default {
  initAudioProcessor,
  unlockAudioContext,
  connectMicrophoneStream,
  disconnectMicrophoneStream,
  setGain,
  getGain,
  getAudioLevel,
  startLevelAnalysis,
  stopLevelAnalysis,
  playAudio,
  startPlayback: playAudio, // 为了兼容测试用例
  stopPlayback,
  isPlaying,
  getMicrophoneStream,
  registerAudioDataCallback,
  setProcessingConfig,
  getProcessingConfig,
  dispose
}; 